/*   The MIT License
 *   
 *   Carina Engine
 *   Copyright (c) 2009 2010 2011 2012 Zdravko Velinov
 *   
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 */

#ifndef UTILS_HH_
#define UTILS_HH_

#include <sstream>
#include <fstream>

#include "carina/common/global.hh"
#include "carina/common/exception.hh"

namespace Carina
{
/*! \brief Converts a string to a value.
 *  \tparam T   the type of the value.
 *  \param t    the variable to which the value is going to be outputted.
 */
template<typename T>
void convert_string(const string& str, T& t)
{
    std::stringstream ss(str);
    ss >> t;
    if(!ss)
        THROW_EXCEPTION("invalid data");
}

/*! \brief Converts the value to string.
 *  \tparam T   the type of the value.
 *  \param t    the value that must be converted.
 *  \return returns the resulting string.
 */
template<typename T>
string convert_value(const T& t)
{
    std::stringstream ss;
    ss << t;
    if(!ss)
        THROW_EXCEPTION("invalid data");
    return ss.str();
}

/*! \brief Parses the contents of a stream into a dynamic array with predetermined size.
 *  \tparam T       the type of the contents of the array.
 *  \param ss       the stream that contains the information that must be parsed.
 *  \param arr      the array into which the parsed value get inserted.
 */
template<typename T>
void parse_array(std::istream& ss, DynamicArray<T>& arr)
{
    for(size_t i = 0; i < arr.size(); ++i)
        ss >> arr[i];
    if(!ss)
        THROW_EXCEPTION("data inconsistency");
}

/*! \brief Parses the contents of a string into a dynamic array with predetermined size.
 *  \tparam T       the type of the contents of the array.
 *  \param s        the string that must be parsed.
 *  \param arr      the array into which the parsed value get inserted.
 */
template<typename T>
void parse_array(const string& s, DynamicArray<T>& arr)
{
    std::stringstream ss(s);
    parse_array(arr, ss);
}

/*! \brief Outputs the contents of a dynamic array to an output stream.
 *  \tparam T       the type of the contents of the array.
 *  \param os       the stream to which the contents are going to be outputted.
 *  \param arr      the array which contains the values that must be outputted.
 */
template<typename T>
std::ostream& operator<<(std::ostream& os, const DynamicArray<T>& arr)
{
    for(size_t i = 0; i < arr.size(); ++i)
        os << arr[i] << '\n';
    return os;
}

inline bool CopyFileToString(const string& name, string& filecontents)
{
    std::ifstream istr(name.c_str());
    if(!istr.is_open())
        return false;

    istr.seekg(0, std::ios::end);   
    filecontents.reserve(static_cast<unsigned>(istr.tellg()));
    istr.seekg(0, std::ios::beg);

    filecontents.assign((std::istreambuf_iterator<char>(istr)),
                        std::istreambuf_iterator<char>());
    return istr.good();
}
}

#endif /* UTILS_HH_ */
